package com.practice.gson;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class Main {

	private static Gson gson = new Gson();

	public static void main(String[] args) {
		/*List<Person> pList = new ArrayList<>();
		Class<?> clazz = pList.getClass();
		System.out.println(clazz);
		Type genericClass = clazz.getGenericSuperclass();
		System.out.println(genericClass);
		Type[] parameterClasses = ((ParameterizedType) genericClass).getActualTypeArguments();
		for (Type pclass : parameterClasses) {
			System.out.println(pclass);
		}
		
		Type type = new TypeToken<List<Person>>(){}.getType();
		System.out.println(type);*/
		
		Person person = new Person();
		person.setName("Lex");
		
		GsonSerializer<Person> serializer = new GsonSerializer<>(Person.class);

		String json = serializer.serialize(person);
		System.out.println(json);

		person = serializer.deserialize(json);
		System.out.println(person.getName());

		List<Person> personList = new ArrayList<>();
		person = new Person();
		person.setName("Leonardo");
		personList.add(person);
		person = new Person();
		person.setName("Letheus");
		personList.add(person);

		json = serializeList(personList);
		System.out.println(json);

		personList = deserializeList(json);
		for (Person p : personList) {
			System.out.println(p.getName());
		}
		/*
		List<List<Person>> personLists = new ArrayList<>(); 
		List<Person> personList = new ArrayList<>();
		Person person = new Person();
		person.setName("Lex");
		personList.add(person);
		personLists.add(personList);

		Gson gson = new Gson();
		
		String json = gson.toJson(personLists);
		System.out.println(json);
		
		personLists = deserializeList(json, new TypeToken<List<Person>>() {}.getType());
		personLists.stream().flatMap(List::stream).forEach(psn -> System.out.println(psn.getName()));*/
	}

	private static String serialize(Person person) {

		return gson.toJson(person);
	}

	private static Person deserialize(String json) {
		Type type = new TypeToken<Person>() {
		}.getType();

		Person obj = gson.fromJson(json, type);
		return obj;
	}

	private static String serializeList(List<Person> personList) {
		return gson.toJson(personList);
	}

	private static List<Person> deserializeList(String json) {
		Type type = new TypeToken<List<Person>>() {

		}.getType();

		List<Person> personList = gson.fromJson(json, type);
		return personList;
	}
	
	private static <T> List<T> deserializeList(String json, Type itemType) {
		Type listType = new ParameterizedType() {
			@Override
			public Type getRawType() {
				
				return List.class;
			}
			@Override
			public Type getOwnerType() {
				
				return null;
			}
			@Override
			public Type[] getActualTypeArguments() {
				Type[] actualTypeArguments = new Type[1];
				actualTypeArguments[0] = itemType;
				return actualTypeArguments;
			}
		};
		return gson.fromJson(json, listType);
	}
}
